﻿//
// Copyright (c) 2024 BPer
//

#include <bperrtc/BPerPushAudio.h>

#include <bperrtc/BPerPush.h>
#include <bperrtc/BPerRtcConnection.h>

#include <bperutil/sys/BPerLog.h>
#include <bperrtp/BPerRtpHeader.h>
#include <bperrtp/BPerRtpPacket.h>
#include <bperrtp/BPerRtpConstant.h>

int32_t bPer_push_audio_encodeAudio(BPerRtcSession *session, BPerPushAudioRtp *rtp,
		BPerRtpPacket *pkt) {
	int err = 0;

	bPer_init_buffer(&rtp->buf, bPer_get_rtpBuffer(rtp->audioRtpBuffer),	kRtpPacketSize);

	if ((err = bPer_encode_rtpHeader(&rtp->buf, &pkt->header)) != BPer_Ok) {
		return bPer_error_wrap(err, "audio rtp header(%d) encode packet fail",
				pkt->payload_type);
	}
	err = bPer_encode_h264_raw(&rtp->buf, &rtp->audioRawData);
	if (err != BPer_Ok) {
		return bPer_error_wrap(err, "audio rtp payload(%d) encode packet fail",
				pkt->payload_type);
	}
	if (pkt->header.padding_length > 0) {
		uint8_t padding = pkt->header.padding_length;
		if (!bPer_buffer_require(&rtp->buf, padding)) {
			return bPer_error_wrap(ERROR_RTC_RTP_MUXER,
					"padding requires %d bytes", padding);
		}
		bPer_memset(rtp->buf.head, padding, padding);
		bPer_buffer_skip(&rtp->buf, padding);
	}

    if(session&&session->context.stats.on_pub_audioRtp){
        session->context.stats.on_pub_audioRtp(&session->context.stats.sendStats,pkt,&rtp->buf);
    }

	return bPer_send_avpacket(session, pkt, &rtp->buf);
}

int32_t bPer_push_audio_rtp(void *psession, BPerPushAudioRtp *rtp,
		BPerFrame *audioFrame) {
	int err = 0;
	BPerRtcSession *session=(BPerRtcSession*)psession;
	bPer_reset_rtpPacket(&rtp->audioRawPacket);
	rtp->audioRawPacket.header.payload_type = session->audioPayloadType;
	rtp->audioRawPacket.header.ssrc = rtp->audioSsrc;
	rtp->audioRawPacket.frame_type = BPerFrameTypeAudio;
	rtp->audioRawPacket.header.marker = BPerTrue;

	rtp->audioRawPacket.header.sequence = rtp->audioSeq++;
	rtp->audioRawPacket.header.timestamp = audioFrame->pts;
	rtp->audioRawPacket.header.padding_length = 0;
	rtp->audioRawPacket.payload_type = BPerRtpPacketPayloadTypeRaw;

	rtp->audioRawData.payload = rtp->audioBuffer;
    rtp->audioRawData.nb = audioFrame->nb;
	bPer_memcpy(rtp->audioRawData.payload, audioFrame->payload,
            rtp->audioRawData.nb);
	if ((err = bPer_push_audio_encodeAudio(session, rtp, &rtp->audioRawPacket))
			!= BPer_Ok) {
		return bPer_error_wrap(err, "encode packet");
	}
	session->context.stats.sendStats.audioRtpPacketCount++;
	return err;
}

void bPer_create_pushAudio(BPerPushAudio* push,BPerRtpBuffer* audioRtpBuffer){
	if (push == NULL)		return;
	BPerPushAudioRtp *rtp=(BPerPushAudioRtp*)bPer_calloc(sizeof(BPerPushAudioRtp),1);
	push->push=rtp;
	rtp->audioBuffer = (char*) bPer_calloc(kRtpPacketSize,1);
	rtp->audioSeq = 0;
	rtp->audioSsrc = 0;
	rtp->audioRtpBuffer = audioRtpBuffer;
	push->on_audio =bPer_push_audio_rtp;

}

void bPer_destroy_pushAudio(BPerPushAudio* push){
	if (push == NULL|| push->push==NULL)		return;
	BPerPushAudioRtp *rtp=push->push;
	bPer_free(rtp->audioBuffer);
	bPer_destroy_rtpPacket(&rtp->audioRawPacket);
	bPer_free(push->push);
}


